﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using ProgNetComponents.Classes;
using System.IO;

namespace System
{
    /// <summary>
    /// Extension methods for Type type
    /// </summary>
    public static class TypeExt
    {
        /// <summary>
        /// Gets the consts values.
        /// </summary>
        /// <param name="type">The type.</param>
        /// <returns></returns>
        public static object[] GetConstsValues(this Type type)
        {
            List<object> list = new List<object>();
            FieldInfo[] fields = type.GetFields(BindingFlags.Public | BindingFlags.Static);
            foreach (FieldInfo fi in fields)
            {
                if (fi.IsLiteral && !fi.IsInitOnly)
                {
                    list.Add(fi.GetValue(null));
                }
            }
            return list.ToArray();
        }

        /// <summary>
        /// Gets the constant value for specified name.
        /// </summary>
        /// <param name="type">The type.</param>
        /// <param name="name">The name.</param>
        /// <returns></returns>
        public static object GetConstValue(this Type type, string name)
        {
            FieldInfo fi = type.GetSingleField(name, BindingFlags.Public | BindingFlags.Static);
            if(fi!=null)
            {
                if (fi.IsLiteral && !fi.IsInitOnly && fi.Name == name)
                {
                    return fi.GetValue(null);
                }
            }
            return null;
        }

        /// <summary>
        /// Gets the consts.
        /// </summary>
        /// <param name="type">The type.</param>
        /// <returns></returns>
        public static NamedObject[] GetConsts(this Type type)
        {
            List<NamedObject> list = new List<NamedObject>();
            FieldInfo[] fields = type.GetFields(BindingFlags.Public | BindingFlags.Static);
            foreach (FieldInfo fi in fields)
            {
                if (fi.IsLiteral && !fi.IsInitOnly)
                {
                    list.Add(new NamedObject(fi.Name, fi.GetValue(null)));
                }
            }
            return list.ToArray();
        }

        /// <summary>
        /// Determines whether [is type of] [the specified value].
        /// </summary>
        /// <param name="val">The value.</param>
        /// <param name="type">The type.</param>
        /// <param name="withInterfaces">if set to <c>true</c> [with interfaces].</param>
        /// <returns></returns>
        public static bool IsTypeOf(this Type val, Type type, bool withInterfaces = false)
        {
            if (val != null)
            {
                if (val.FullName == type.FullName)
                    return true;
                if (withInterfaces)
                {
                    Type[] interfaces;
                    interfaces = val.GetInterfaces();
                    if (interfaces != null)
                    {
                        foreach (Type iType in interfaces)
                        {
                            if (iType.FullName == type.FullName)
                                return true;
                        }
                    }
                }
                return val.BaseType.IsTypeOf(type, withInterfaces);
            }
            return false;
        }
    }
}
